使用 WorkManager 处理需要立刻执行的后台任务
后台执行限制
https://developer.android.google.cn/about/versions/oreo/background
API 介绍
WorkManager 版本 2.3.0
https://developer.android.google.cn/jetpack/androidx/releases/work#version_230_3
ListenableWorker
https://developer.android.google.cn/reference/androidx/work/ListenableWorker
setForegroundAsync()
https://developer.android.google.cn/reference/kotlin/androidx/work/ListenableWorker#setforegroundasync
CoroutineWorker
https://developer.android.google.cn/reference/kotlin/androidx/work/CoroutineWorker
setForeground()
https://developer.android.google.cn/reference/kotlin/androidx/work/CoroutineWorker#setforeground
从立即执行开始
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
override suspend fun doWork(): Result {
try {
//要执行的代码
return Result.success()
} catch (throwable: Throwable) {
//进行清理并输出
return Result.failure()
}
}
ForegroundInfo
https://developer.android.google.cn/reference/androidx/work/ForegroundInfo
Notification
https://developer.android.google.cn/reference/android/app/Notification
创建 ForegroundInfo
正确创建 ForegroundInfo 只需如下三步:
创建一个 Notification
创建一个 Notification Channel
将通知引入 ForegroundInfo
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
/**
*为前台服务运行的 Worker 创建 ForegroundInfo
*/
private fun createForegroundInfo(): ForegroundInfo {
//每一个 Notification 需要使用不同的 id
val notificationId = 1
return ForegroundInfo(notificationId, createNotification())
}
/**
* 为前台服务运行任务创建 Notification 和所需的 channel (Andrid O版本以上)
*/
private fun createNotification(): Notification {
//PendingIntent 可用来取消 Worker
val intent = WorkManager.getInstance(context).createCancelPendingIntent(id)
val builder = Builder(context, channelId)
.setContentTitle(title)
.setTicker(title)
.setSmallIcon(R.drawable.baseline_gradient)
.setOngoing(true)
.addAction(drawable.ic_delete, cancel, intent)
if (VERSION.SDK_INT >= VERSION_CODES.O) {
createNotificationChannel(channelId, name).also {
builder.setChannelId(it.id)
}
}
return builder.build()
}
/**
* 为 Android O 及以上版本的设备创建所需的 notification channel
*/
@TargetApi(VERSION_CODES.O)
private fun createNotificationChannel(
channelId: String,
name: String
): NotificationChannel {
return NotificationChannel(
channelId, name, NotificationManager.IMPORTANCE_LOW
).also { channel ->
notificationManager.createNotificationChannel(channel)
}
}
在前台服务中执行任务
现在把这些整合起来。我们已经实现了 doWork 函数,我们可以调用 setForeground(),并且通过调用 createForegroundInfo() 来传递所需的信息。
/* Copyright 2020 Google LLC.
SPDX-License-Identifier: Apache-2.0 */
override suspend fun doWork(): Result {
try {
setForeground(createForegroundInfo())
//需要执行的代码
return Result.success(workDataOf(KEY_RESULT to result))
} catch (throwable: Throwable) {
//进行清理并且输出日志
return Result.failure()
}
}
⚠️⚠️⚠️
在长时间运行任务开始之前,先调用 setForeground()。 否则在 setForeground() 被调用之前,您的 Worker 将会被视为非前台服务,这样可能会导致这个任务被取消或引起其余不希望出现的结果。 ⚠️⚠️⚠️
下一步
示例代码
https://github.com/android/architecture-components-samples/tree/master/WorkManagerSample
在前台服务中执行任务的代码,请查阅:
BaseFilterWorker 类
https://github.com/android/architecture-components-samples/blob/master/WorkManagerSample/lib/src/main/java/com/example/background/workers/BaseFilterWorker.kt
提交记录
https://github.com/android/architecture-components-samples/commit/160f148b5ea4c943028c73acd4667fd134a8674e
关于长时间运行 worker 和前台服务的详细指南,以及主题更多信息,请查阅:
WorkManager 的高级指南|支持长时间运行的工作器
https://developer.android.google.cn/topic/libraries/architecture/workmanager/advanced/long-running
后台处理指南
https://developer.android.google.cn/guide/background
Android 上的 Kotlin 协程
https://developer.android.google.cn/kotlin/coroutines
WorkManager 系列文章助您了解 WorkManager 从基础到高级的各项特性:
Google IssueTracker
http://goo.gle/workmanager-issue
推荐阅读